#include "littlefs.h"
#include "board.h"

#if 0
#define DEBUG(format,...) printf(""format"", ##__VA_ARGS__) 
#else
#define DEBUG(...)
#endif

static int _read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
{
    unsigned int address;
    address = c->block_size * block + off + USER_DATA_FIELD_START;
    flash_read(address, buffer, size);
    return 0;
}

static int _prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
{
    unsigned int address;
    address = c->block_size * block + off + USER_DATA_FIELD_START;
    flash_write(address, (void *)buffer, size);
    return 0;
}

static int _erase(const struct lfs_config *c, lfs_block_t block)
{
    unsigned int address;
    address = c->block_size * block + USER_DATA_FIELD_START;
    flash_erase(address);
    return 0;
}

int _sync(const struct lfs_config *c)
{
    return 0;
}

#define LFS_CACHE_SIZE      256
unsigned char read_buf[LFS_CACHE_SIZE];
unsigned char prog_buf[LFS_CACHE_SIZE];
unsigned char file_cache[LFS_CACHE_SIZE];
unsigned char lookahead_buf[4];
littlefs_t f030_fs;

struct lfs_config lfs_cfg = {
    // block device operations
    .read  = _read,
    .prog  = _prog,
    .erase = _erase,
    .sync  = _sync,

    // block device configuration
    .read_size = LFS_CACHE_SIZE,
    .prog_size = LFS_CACHE_SIZE,
    .block_size = 2048,
    .block_count = 62,
    .cache_size = LFS_CACHE_SIZE,
    .lookahead_size = 2,
    .block_cycles = 100,
    .read_buffer = (void*)read_buf,
    .prog_buffer = (void*)prog_buf,
    .lookahead_buffer = (void*)lookahead_buf,
};

struct lfs_file_config lfs_file_cfg = {
    .buffer = (void*)file_cache,
    .attrs = NULL,
    .attr_count = 0
};

int filesystem_init(void)
{
    int ret;
    littlefs_init(&f030_fs, &lfs_cfg, &lfs_file_cfg);
    DEBUG("filesystem_init: littlefs mount                  ");
    ret = f030_fs.mount(f030_fs.lfs, &lfs_cfg);
    if(ret != LFS_ERR_OK)
    {
        DEBUG("[FAIL]\n");
        DEBUG("filesystem_init: STM32F030CCT6 Flash format      ");
        if(f030_fs.format(f030_fs.lfs, &lfs_cfg)) 
        {
            DEBUG("[FAIL]\n");
            while(1);
        }
        DEBUG("[ OK ]\n");
        DEBUG("filesystem_init: littlefs remount                ");
        f030_fs.mount(f030_fs.lfs, &lfs_cfg);
    }
    DEBUG("[ OK ]\n");
    DEBUG("filesystem_init: Flash available size: %d Bytes\n", f030_fs.free());
    return 0;
}

